{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from selenium import webdriver\n",
    "from selenium.webdriver.common.by import By\n",
    "from selenium.webdriver.common.keys import Keys\n",
    "from selenium.webdriver.support.ui import WebDriverWait\n",
    "from selenium.webdriver.support import expected_conditions as EC\n",
    "from selenium.webdriver.support.expected_conditions import *\n",
    "from selenium.webdriver.edge.service import Service as EdgeService\n",
    "from webdriver_manager.microsoft import EdgeChromiumDriverManager\n",
    "\n",
    "import time\n",
    "import json\n",
    "import os\n",
    "import csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://10.113.178.219'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "\n",
    "def open_driver(url):\n",
    "    options = webdriver.EdgeOptions()\n",
    "    options.add_experimental_option('excludeSwitches', ['enable-logging'])  # 忽略警告和错误\n",
    "    service = EdgeService(EdgeChromiumDriverManager().install())\n",
    "    driver = webdriver.Edge(service=service, options=options)\n",
    "    driver.get(url)\n",
    "    driver.implicitly_wait(5)  # 设置浏览器驱动的等待时间限制\n",
    "    driver.maximize_window()\n",
    "    return driver\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 0: Login\n",
    "\n",
    "The first task is to complete the following code blocks to login our CDS Shop website using Selenium.\n",
    "1. Go to login page\n",
    "2. Keyin your account and password \n",
    "3. Press login button"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def login(driver):\n",
    "    account = 'mc46526'+'@um.edu.mo'  # Replace with your account\n",
    "    password = 'mc46526'  # Replace with your password\n",
    "\n",
    "    driver.get(url)  # Replace with the actual login page URL\n",
    "    try:\n",
    "        print(\"Navigated to login page\")\n",
    "        # Wait for the sign-in page button to appear\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/header/nav/div/div/div/a[2]\")))\n",
    "        sign_in_page_button = driver.find_element(By.XPATH, \"/html/body/div/header/nav/div/div/div/a[2]\")\n",
    "        print(\"Sign in button found\")\n",
    "        sign_in_page_button.click()\n",
    "\n",
    "        # Wait for the account input field to appear\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[1]/input\")))\n",
    "        account_input = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[1]/input\")\n",
    "        print(\"Account input found\")\n",
    "        account_input.send_keys(account)\n",
    "\n",
    "        # Wait for the password input field to appear\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[2]/input\")))\n",
    "        password_input = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[2]/input\")\n",
    "        print(\"Password input found\")\n",
    "        password_input.send_keys(password)\n",
    "\n",
    "        # Wait for the login button to appear\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/form/button\")))\n",
    "        sign_in = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/button\")\n",
    "        print(\"Login button found\")\n",
    "        sign_in.click()\n",
    "\n",
    "        print(\"Login successful\")\n",
    "        \n",
    "        # Add a delay to observe the login result\n",
    "        time.sleep(5)  # Adjust the delay time as needed\n",
    "\n",
    "    except Exception as e:\n",
    "        print(f\"An error occurred: {e}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Navigated to login page\n",
      "Sign in button found\n",
      "Account input found\n",
      "Password input found\n",
      "Login button found\n",
      "Login successful\n"
     ]
    }
   ],
   "source": [
    "def t0():\n",
    "    driver = open_driver(url)\n",
    "    login(driver)\n",
    "    driver.close()\n",
    "\n",
    "t0()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1: Place an order\n",
    "\n",
    "This task requires you to place an order to purchase 5 units of the last product available on the CDS shop.\n",
    "\n",
    "1. Go to last page\n",
    "2. Find the last product\n",
    "3. Set the quantity as 5\n",
    "4. Press add to Cart\n",
    "5. Proceed to check out\n",
    "6. Fill shipping information (type anything in the postal address...)\n",
    "7. Continue until you reach the payment page"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "def go_to_last_page(driver):\n",
    "    try:\n",
    "        # Wait for the pagination controls to be present\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/ul\")))\n",
    "        \n",
    "        # Find the pagination control\n",
    "        pagination = driver.find_element(By.XPATH, \"/html/body/div/main/div/ul\")\n",
    "        \n",
    "        # Find all page buttons within the pagination control\n",
    "        page_buttons = pagination.find_elements(By.CLASS_NAME, \"page-link\")\n",
    "        \n",
    "        # Click the last page button\n",
    "        if page_buttons:\n",
    "            last_page_button = page_buttons[-1]\n",
    "            last_page_button.click()\n",
    "            print(\"Navigated to the last page\")\n",
    "        else:\n",
    "            print(\"No page buttons found\")\n",
    "    except Exception as e:\n",
    "        print(f\"An error occurred while navigating to the last page: {e}\")\n",
    "    \n",
    "    return driver"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [],
   "source": [
    "from selenium import webdriver\n",
    "from selenium.webdriver.common.by import By\n",
    "from selenium.webdriver.support.ui import WebDriverWait\n",
    "from selenium.webdriver.support import expected_conditions as EC\n",
    "from selenium.webdriver.support.ui import Select\n",
    "\n",
    "def place_an_order_on_last_product(driver):\n",
    "    try:\n",
    "        # Wait for the product list to be present\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, \"row\")))\n",
    "        print(\"Product list found\")\n",
    "\n",
    "        # Find the product list\n",
    "        product_list = driver.find_element(By.CLASS_NAME, \"row\")\n",
    "        \n",
    "        # Find all products within the product list\n",
    "        products = product_list.find_elements(By.CLASS_NAME, \"col-xl-3\")\n",
    "        print(f\"Number of products found: {len(products)}\")\n",
    "        \n",
    "        # Find the last product\n",
    "        if products:\n",
    "            last_product = products[-1]\n",
    "            print(\"Last product found\")\n",
    "            \n",
    "            # Click on the last product's link to view details\n",
    "            last_product_link = last_product.find_element(By.XPATH, \".//a[@href]\")\n",
    "            last_product_link.click()\n",
    "            print(\"Clicked on the last product link\")\n",
    "            \n",
    "            # Confirm the product details page is loaded by checking the presence of the return button\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/a\")))\n",
    "            print(\"Product details page loaded\")\n",
    "            \n",
    "            # Wait for the quantity select field to be present\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div[1]/div[3]/div/div/div[3]/div/div[2]/select\")))\n",
    "            quantity_select = driver.find_element(By.XPATH, \"/html/body/div/main/div/div[1]/div[3]/div/div/div[3]/div/div[2]/select\")\n",
    "            print(\"Quantity select found\")\n",
    "            \n",
    "            # Set the quantity to 5\n",
    "            select = Select(quantity_select)\n",
    "            select.select_by_value(\"5\")\n",
    "            print(\"Quantity set to 5\")\n",
    "            \n",
    "            # Wait for the \"Add to Cart\" button to be present\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div[1]/div[3]/div/div/div[4]/button\")))\n",
    "            add_to_cart_button = driver.find_element(By.XPATH, \"/html/body/div/main/div/div[1]/div[3]/div/div/div[4]/button\")\n",
    "            add_to_cart_button.click()\n",
    "            print(\"Added to cart\")\n",
    "            \n",
    "            # Proceed to checkout\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div[2]/div/div/div[2]/button\")))\n",
    "            checkout_button = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div[2]/div/div/div[2]/button\")\n",
    "            checkout_button.click()\n",
    "            print(\"Proceeded to checkout\")\n",
    "            \n",
    "            # Fill in shipping information\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[1]/input\")))\n",
    "            shipping_address = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[1]/input\")\n",
    "            shipping_address.send_keys(\"123 Main St, Anytown, USA\")\n",
    "            print(\"Shipping information filled\")\n",
    "            \n",
    "            # Continue to the payment page\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/form/button\")))\n",
    "            continue_to_payment_button = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/button\")\n",
    "            continue_to_payment_button.click()\n",
    "            print(\"Continued to payment page\")\n",
    "            \n",
    "        else:\n",
    "            print(\"No products found\")\n",
    "    except Exception as e:\n",
    "        print(f\"An error occurred while placing an order: {e}\")\n",
    "    \n",
    "    return 0\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Navigated to the last page\n",
      "Product list found\n",
      "Number of products found: 2\n",
      "Last product found\n",
      "Clicked on the last product link\n",
      "Product details page loaded\n",
      "Quantity select found\n",
      "Quantity set to 5\n",
      "Added to cart\n",
      "Proceeded to checkout\n",
      "Shipping information filled\n",
      "Continued to payment page\n"
     ]
    }
   ],
   "source": [
    "def t1():\n",
    "    driver = open_driver(url)\n",
    "    driver = go_to_last_page(driver)\n",
    "    place_an_order_on_last_product(driver)\n",
    "    driver.close()\n",
    "\n",
    "t1()   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2: Fetch the products with specific review rating\n",
    "\n",
    "This task requires you to retrieve products with a review rating greater than or equal to 2.5.\n",
    "\n",
    "1. Iterate all pages.\n",
    "2. Open product page in new tab.\n",
    "3. Find the review column.\n",
    "4. Find the pattern of rating(empty filled, half filled, full filled)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def go_to_next_page(driver):\n",
    "    try:\n",
    "        # Wait for pagination to be present\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, \"pagination\")))\n",
    "        pagination = driver.find_element(By.CLASS_NAME, \"pagination\")\n",
    "        \n",
    "        # Find all page links\n",
    "        page_links = pagination.find_elements(By.CLASS_NAME, \"page-link\")\n",
    "        \n",
    "        # Find the active page number\n",
    "        active_page = pagination.find_element(By.CLASS_NAME, \"active\")\n",
    "        current_page_num = int(active_page.text)\n",
    "        \n",
    "        # Click next page if it exists\n",
    "        for link in page_links:\n",
    "            if link.text.isdigit() and int(link.text) == current_page_num + 1:\n",
    "                link.click()\n",
    "                # Wait for page to load\n",
    "                time.sleep(2)\n",
    "                return True\n",
    "                \n",
    "        return False  # No more pages\n",
    "        \n",
    "    except Exception as e:\n",
    "        print(f\"Error navigating to next page: {e}\")\n",
    "        return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_review(driver):\n",
    "    try:\n",
    "        # Wait for rating element to be present\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, \"rating\")))\n",
    "        \n",
    "        # Count full stars\n",
    "        full_stars = len(driver.find_elements(By.CSS_SELECTOR, \".rating .fas.fa-star\"))\n",
    "        \n",
    "        # Count half stars\n",
    "        half_stars = len(driver.find_elements(By.CSS_SELECTOR, \".rating .fas.fa-star-half-alt\"))\n",
    "        \n",
    "        # Calculate total rating\n",
    "        rating = full_stars + (half_stars * 0.5)\n",
    "        \n",
    "        return rating\n",
    "        \n",
    "    except Exception as e:\n",
    "        print(f\"Error getting review: {e}\")\n",
    "        return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "def open_products_in_new_tab(driver):\n",
    "    products_rating = {}\n",
    "    \n",
    "    try:\n",
    "        # Wait for product cards to be present\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, \"card\")))\n",
    "        \n",
    "        # Get all product cards\n",
    "        product_cards = driver.find_elements(By.CLASS_NAME, \"card\")\n",
    "        \n",
    "        for card in product_cards:\n",
    "            # Get product name\n",
    "            name = card.find_element(By.CSS_SELECTOR, \".card-body strong\").text\n",
    "            \n",
    "            # Get product link\n",
    "            link = card.find_element(By.CSS_SELECTOR, \".card-body a\").get_attribute(\"href\")\n",
    "            \n",
    "            # Open product in new tab\n",
    "            driver.execute_script(f\"window.open('{link}', '_blank')\")\n",
    "            \n",
    "            # Switch to new tab\n",
    "            driver.switch_to.window(driver.window_handles[-1])\n",
    "            \n",
    "            # Get review rating\n",
    "            rating = get_review(driver)\n",
    "            \n",
    "            if rating >= 2.5:\n",
    "                products_rating[name] = rating\n",
    "            \n",
    "            # Close tab and switch back\n",
    "            driver.close()\n",
    "            driver.switch_to.window(driver.window_handles[0])\n",
    "            \n",
    "        return products_rating\n",
    "        \n",
    "    except Exception as e:\n",
    "        print(f\"Error processing products: {e}\")\n",
    "        return {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Navigated to login page\n",
      "Sign in button found\n",
      "Account input found\n",
      "Password input found\n",
      "Login button found\n",
      "Login successful\n",
      "Error navigating to next page: invalid literal for int() with base 10: '1\\n(current)'\n",
      "\n",
      "Products with rating >= 2.5:\n",
      "- 19th centery Flower Art Roman emperor: 4.0\n",
      "- WorldWide Roman emperor Wax Stamp Vintage: 5.0\n",
      "128GB OPPO Watch Plus 5G Pro: 3.0\n",
      "256GB 5G Redmi Note red 2nd Generation: 5.0\n",
      "2nd Generation 64GB red OPPO Watch 3rd Generation: 5.0\n",
      "3rd Generation 2nd Generation red headsets Gold: 4.0\n",
      "3rd Generation Gold 128GB cell Phones_smartphones Apple: 3.0\n"
     ]
    }
   ],
   "source": [
    "def t2():\n",
    "    try:\n",
    "        driver = open_driver(url)\n",
    "        login(driver)\n",
    "        high_rated_products = {}\n",
    "        \n",
    "        while True:\n",
    "            # Get products from current page\n",
    "            page_products = open_products_in_new_tab(driver)\n",
    "            high_rated_products.update(page_products)\n",
    "            \n",
    "            # Try to go to next page\n",
    "            if not go_to_next_page(driver):\n",
    "                break\n",
    "                \n",
    "        print(\"\\nProducts with rating >= 2.5:\")\n",
    "        for product, rating in high_rated_products.items():\n",
    "            print(f\"{product}: {rating}\")\n",
    "            \n",
    "        driver.close()\n",
    "        \n",
    "    except Exception as e:\n",
    "        print(f\"Error in main task: {e}\")\n",
    "        driver.quit()\n",
    "\n",
    "# Execute Task 2\n",
    "t2()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 3: Purchase the 10 most expensive products.\n",
    "This task entails adding the 10 most expensive products to the cart in a **single order** and proceeding with the payment.\n",
    "\n",
    "To proceed with the payment, you are required to pass a **captcha code test** using the [\"ddddocr\"](https://github.com/sml2h3/ddddocr) library.\n",
    "\n",
    "1. Empty the carts\n",
    "2. Get the names of the 10 most expensive products.\n",
    "3. Add them into cart by searching products name.\n",
    "4. Place the order when all the products are in the carts.\n",
    "5. Proceed the payment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def empty_carts(driver):\n",
    "    \"\"\"\n",
    "    Empty all items in the shopping cart\n",
    "    Args:\n",
    "        driver: WebDriver instance\n",
    "    Returns:\n",
    "        driver: WebDriver instance after emptying cart\n",
    "    \"\"\"\n",
    "    try:\n",
    "        # Click the cart button to go to the cart page\n",
    "        cart_button = driver.find_element(By.XPATH, '/html/body/div/header/nav/div/div/div/a')\n",
    "        cart_button.click()\n",
    "        \n",
    "        while True:\n",
    "            try:\n",
    "                # Find and click the delete button for each item in the cart\n",
    "                delete_buttons = driver.find_elements(By.CSS_SELECTOR, \"button.btn.btn-light > i.fas.fa-trash\")\n",
    "                if not delete_buttons:\n",
    "                    break\n",
    "                for button in delete_buttons:\n",
    "                    button.click()\n",
    "                    WebDriverWait(driver, 10).until(\n",
    "                        EC.presence_of_element_located((By.CSS_SELECTOR, \"div.fade.alert.alert-info.show\"))\n",
    "                    )\n",
    "            except Exception as e:\n",
    "                print(f\"An error occurred while deleting items: {e}\")\n",
    "                break\n",
    "        \n",
    "        print(\"Cart emptied successfully\")\n",
    "        \n",
    "        # Click the \"Go Back\" link to return to the initial page\n",
    "        go_back_link = driver.find_element(By.XPATH, '//a[text()=\"Go Back\"]')\n",
    "        go_back_link.click()\n",
    "        print(\"Returned to the initial page\")\n",
    "        \n",
    "    except Exception as e:\n",
    "        print(f\"An error occurred: {e}\")\n",
    "    \n",
    "    return driver\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "from selenium.webdriver.common.by import By\n",
    "\n",
    "def fetch_top10_names(driver):\n",
    "    products = []\n",
    "    \n",
    "    while True:\n",
    "        # Locate all product elements on the page\n",
    "        product_elements = driver.find_elements(By.XPATH, '/html/body/div/main/div/div[2]/div')\n",
    "        \n",
    "        for product in product_elements:\n",
    "            # Extract the product name\n",
    "            name = product.find_element(By.XPATH, './/div[@class=\"card-title\"]/strong').text\n",
    "            # Extract the product price\n",
    "            price_text = product.find_element(By.XPATH, './/h3[@class=\"card-text\"]').text\n",
    "            price = float(price_text.replace('$', ''))\n",
    "            \n",
    "            products.append((name, price))\n",
    "        \n",
    "        # Try to go to the next page\n",
    "        if not go_to_next_page(driver):\n",
    "            break\n",
    "    \n",
    "    # Sort products by price in descending order and get the top 10\n",
    "    top10_products = sorted(products, key=lambda x: x[1], reverse=True)[:10]\n",
    "    \n",
    "    # Print the names and prices of the top 10 products\n",
    "    for product in top10_products:\n",
    "        print(f\"{product[0]}: ${product[1]}\")\n",
    "    \n",
    "    return [product[0] for product in top10_products]\n",
    "\n",
    "# Example usage\n",
    "# driver = open_driver(url)\n",
    "# top10_names = fetch_top10_names(driver)\n",
    "# print(top10_names)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def place_products_orders(driver, names):\n",
    "    \"\"\"\n",
    "    Add products to cart by searching their names\n",
    "    Args:\n",
    "        driver: WebDriver instance\n",
    "        names: List of product names to order\n",
    "    Returns:\n",
    "        success_count: Number of successfully added products\n",
    "    \"\"\"\n",
    "    success_count = 0\n",
    "    \n",
    "    for name in names:\n",
    "        try:\n",
    "            # Navigate to home page\n",
    "            driver.get(url)\n",
    "            \n",
    "            # Find and fill search box\n",
    "            search_box = driver.find_element(By.NAME, \"q\")\n",
    "            search_box.clear()\n",
    "            search_box.send_keys(name)\n",
    "            \n",
    "            # Click search button\n",
    "            search_button = driver.find_element(By.XPATH, \"//button[@type='submit']\")\n",
    "            search_button.click()\n",
    "            \n",
    "            # Wait for the product link to be present and click it\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '/html/body/div/main/div/div/div[1]/div/div/a/div/strong')))\n",
    "            product_link = driver.find_element(By.XPATH, '/html/body/div/main/div/div/div[1]/div/div/a/div/strong')\n",
    "            product_link.click()\n",
    "            \n",
    "            # Wait for the add to cart button to be present and click it\n",
    "            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '/html/body/div/main/div/div[1]/div[3]/div/div/div[4]/button')))\n",
    "            add_to_cart_button = driver.find_element(By.XPATH, '/html/body/div/main/div/div[1]/div[3]/div/div/div[4]/button')\n",
    "            add_to_cart_button.click()\n",
    "            \n",
    "            success_count += 1\n",
    "            print(f\"Added {name} to cart\")\n",
    "            \n",
    "            # Navigate back to the main page\n",
    "            main_page_button = driver.find_element(By.XPATH, '/html/body/div/header/nav/div/a')\n",
    "            main_page_button.click()\n",
    "            \n",
    "        except Exception as e:\n",
    "            print(f\"Failed to add {name} to cart: {str(e)}\")\n",
    "    \n",
    "    return success_count\n",
    "\n",
    "# Example usage\n",
    "# driver = open_driver(url)\n",
    "# top10_names = fetch_top10_names(driver)\n",
    "# success_count = place_products_orders(driver, top10_names)\n",
    "# print(f\"Successfully added {success_count} products to cart\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import base64\n",
    "import ddddocr\n",
    "from selenium.webdriver.common.by import By\n",
    "from selenium.webdriver.support.ui import WebDriverWait\n",
    "from selenium.webdriver.support import expected_conditions as EC\n",
    "import time\n",
    "\n",
    "def pay_for_order(driver):\n",
    "    \"\"\"\n",
    "    Process payment with captcha verification\n",
    "    Args:\n",
    "        driver: WebDriver instance\n",
    "    Returns:\n",
    "        status: Payment status (1 for success, 0 for failure)\n",
    "    \"\"\"\n",
    "    try:\n",
    "        # Navigate to cart and click checkout\n",
    "        driver.get(url + \"/cart\")\n",
    "        checkout_button = driver.find_element(By.XPATH, '/html/body/div/main/div/div/div[2]/div/div/div[2]/button')\n",
    "        checkout_button.click()\n",
    "        \n",
    "        # Fill in shipping information\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[1]/input\")))\n",
    "        street_address = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[1]/input\")\n",
    "        city = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[2]/input\")\n",
    "        house_number = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[3]/input\")\n",
    "        country = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/div[4]/input\")\n",
    "        \n",
    "        street_address.send_keys(\"Main St\")\n",
    "        city.send_keys(\"Anytown\")\n",
    "        house_number.send_keys(\"123\")\n",
    "        country.send_keys(\"USA\")\n",
    "        \n",
    "        # Continue to the payment page\n",
    "        continue_to_payment_button = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/button\")\n",
    "        continue_to_payment_button.click()\n",
    "        \n",
    "        # Wait for 1 second and ensure the text appears on the page\n",
    "        time.sleep(1)\n",
    "        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, \"/html/body/div/main/div/div/div/div/h1\")))\n",
    "        \n",
    "        # Click the button again to proceed\n",
    "        continue_to_payment_button = driver.find_element(By.XPATH, \"/html/body/div/main/div/div/div/div/form/button\")\n",
    "        continue_to_payment_button.click()\n",
    "        \n",
    "        # Click the next button to proceed with payment\n",
    "        next_button = driver.find_element(By.XPATH, '/html/body/div/main/div/div[2]/div[2]/div/div/div[7]/button')\n",
    "        next_button.click()\n",
    "        \n",
    "        # Initialize OCR\n",
    "        ocr = ddddocr.DdddOcr()\n",
    "        \n",
    "        # Handle captcha\n",
    "        max_attempts = 3\n",
    "        for attempt in range(max_attempts):\n",
    "            try:\n",
    "                # Get captcha image\n",
    "                captcha_img = driver.find_element(By.XPATH, '/html/body/div/main/div/div/div[2]/div/div/div[6]/div/div/div[1]/div/canvas')\n",
    "                img_base64 = captcha_img.screenshot_as_base64\n",
    "                img_bytes = base64.b64decode(img_base64)\n",
    "                \n",
    "                # Solve captcha\n",
    "                captcha_result = ocr.classification(img_bytes)\n",
    "                \n",
    "                # Input captcha\n",
    "                captcha_input = driver.find_element(By.XPATH, '/html/body/div/main/div/div/div[2]/div/div/div[6]/div/div/div[2]/div/input')\n",
    "                captcha_input.clear()\n",
    "                captcha_input.send_keys(captcha_result)\n",
    "                \n",
    "                # Submit payment\n",
    "                submit_button = driver.find_element(By.XPATH, '/html/body/div/main/div/div/div[2]/div/div/div[6]/div/div/div[3]/div/button')\n",
    "                submit_button.click()\n",
    "                \n",
    "                # Check for success message\n",
    "                WebDriverWait(driver, 5).until(\n",
    "                    EC.presence_of_element_located((By.CLASS_NAME, \"success-message\"))\n",
    "                )\n",
    "                print(\"Payment successful!\")\n",
    "                return 1\n",
    "                \n",
    "            except Exception as e:\n",
    "                print(f\"Captcha attempt {attempt + 1} failed: {str(e)}\")\n",
    "                if attempt == max_attempts - 1:\n",
    "                    print(\"Max captcha attempts reached\")\n",
    "                    return 0\n",
    "                \n",
    "    except Exception as e:\n",
    "        print(f\"Payment failed: {str(e)}\")\n",
    "        return 0\n",
    "\n",
    "# Example usage\n",
    "# driver = open_driver(url)\n",
    "# login(driver)\n",
    "# empty_carts(driver)\n",
    "# top10_names = fetch_top10_names(driver)\n",
    "# place_products_orders(driver, top10_names)\n",
    "# pay_for_order(driver)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Navigated to login page\n",
      "Sign in button found\n",
      "Account input found\n",
      "Password input found\n",
      "Login button found\n",
      "Login successful\n",
      "Cart emptied successfully\n",
      "Returned to the initial page\n",
      "Error navigating to next page: invalid literal for int() with base 10: '1\\n(current)'\n",
      "- WorldWide Roman emperor Wax Stamp Vintage: $903.99\n",
      "3rd Generation 2nd Generation red headsets Gold: $623.99\n",
      "2021 Apple TV 4K 32GB: $570.99\n",
      "- Art Asia Roman emperor Used: $552.99\n",
      "19th centery Style Wax Stamp Used Butterfly: $521.99\n",
      "3rd Generation Gold 128GB cell Phones_smartphones Apple: $493.99\n",
      "128GB OPPO Watch Plus 5G Pro: $343.99\n",
      "2nd Generation 64GB red OPPO Watch 3rd Generation: $245.99\n",
      "256GB 5G Redmi Note red 2nd Generation: $170.99\n",
      "- 19th centery Flower Art Roman emperor: $66.99\n",
      "Added - WorldWide Roman emperor Wax Stamp Vintage to cart\n",
      "Added 3rd Generation 2nd Generation red headsets Gold to cart\n",
      "Added 2021 Apple TV 4K 32GB to cart\n",
      "Added - Art Asia Roman emperor Used to cart\n",
      "Added 19th centery Style Wax Stamp Used Butterfly to cart\n",
      "Added 3rd Generation Gold 128GB cell Phones_smartphones Apple to cart\n",
      "Added 128GB OPPO Watch Plus 5G Pro to cart\n",
      "Added 2nd Generation 64GB red OPPO Watch 3rd Generation to cart\n",
      "Added 256GB 5G Redmi Note red 2nd Generation to cart\n",
      "Added - 19th centery Flower Art Roman emperor to cart\n",
      "欢迎使用ddddocr，本项目专注带动行业内卷，个人博客:wenanzhe.com\n",
      "训练数据支持来源于:http://146.56.204.113:19199/preview\n",
      "爬虫框架feapder可快速一键接入，快速开启爬虫之旅：https://github.com/Boris-code/feapder\n",
      "谷歌reCaptcha验证码 / hCaptcha验证码 / funCaptcha验证码商业级识别接口：https://yescaptcha.com/i/NSwk7i\n",
      "Captcha attempt 1 failed: Message: no such element: Unable to locate element: {\"method\":\"xpath\",\"selector\":\"/html/body/div/main/div/div/div[2]/div/div/div[6]/div/div/div[1]/div/canvas\"}\n",
      "  (Session info: MicrosoftEdge=130.0.2849.56); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception\n",
      "Stacktrace:\n",
      "\tGetHandleVerifier [0x00007FF612D7DC75+12853]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF6130283C4+2250276]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612F676A6+1460486]\n",
      "\t(No symbol) [0x00007FF612B797CC]\n",
      "\t(No symbol) [0x00007FF612B7990C]\n",
      "\t(No symbol) [0x00007FF612BB3857]\n",
      "\t(No symbol) [0x00007FF612B9853F]\n",
      "\t(No symbol) [0x00007FF612B70617]\n",
      "\t(No symbol) [0x00007FF612BB1431]\n",
      "\t(No symbol) [0x00007FF612B98163]\n",
      "\t(No symbol) [0x00007FF612B6FB54]\n",
      "\t(No symbol) [0x00007FF612B6F000]\n",
      "\t(No symbol) [0x00007FF612B6F741]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFCDB4+1024020]\n",
      "\tMicrosoft::Applications::Events::EventProperty::~EventProperty [0x00007FF612C99A04+57108]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFBDB3+1019923]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFBA19+1019001]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1E031+394913]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1A954+380868]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1AA99+381193]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D12296+346374]\n",
      "\tBaseThreadInitThunk [0x00007FFD5F417374+20]\n",
      "\tRtlUserThreadStart [0x00007FFD6123CC91+33]\n",
      "\n",
      "Captcha attempt 2 failed: Message: no such element: Unable to locate element: {\"method\":\"xpath\",\"selector\":\"/html/body/div/main/div/div/div[2]/div/div/div[6]/div/div/div[1]/div/canvas\"}\n",
      "  (Session info: MicrosoftEdge=130.0.2849.56); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception\n",
      "Stacktrace:\n",
      "\tGetHandleVerifier [0x00007FF612D7DC75+12853]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF6130283C4+2250276]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612F676A6+1460486]\n",
      "\t(No symbol) [0x00007FF612B797CC]\n",
      "\t(No symbol) [0x00007FF612B7990C]\n",
      "\t(No symbol) [0x00007FF612BB3857]\n",
      "\t(No symbol) [0x00007FF612B9853F]\n",
      "\t(No symbol) [0x00007FF612B70617]\n",
      "\t(No symbol) [0x00007FF612BB1431]\n",
      "\t(No symbol) [0x00007FF612B98163]\n",
      "\t(No symbol) [0x00007FF612B6FB54]\n",
      "\t(No symbol) [0x00007FF612B6F000]\n",
      "\t(No symbol) [0x00007FF612B6F741]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFCDB4+1024020]\n",
      "\tMicrosoft::Applications::Events::EventProperty::~EventProperty [0x00007FF612C99A04+57108]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFBDB3+1019923]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFBA19+1019001]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1E031+394913]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1A954+380868]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1AA99+381193]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D12296+346374]\n",
      "\tBaseThreadInitThunk [0x00007FFD5F417374+20]\n",
      "\tRtlUserThreadStart [0x00007FFD6123CC91+33]\n",
      "\n",
      "Captcha attempt 3 failed: Message: no such element: Unable to locate element: {\"method\":\"xpath\",\"selector\":\"/html/body/div/main/div/div/div[2]/div/div/div[6]/div/div/div[1]/div/canvas\"}\n",
      "  (Session info: MicrosoftEdge=130.0.2849.56); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception\n",
      "Stacktrace:\n",
      "\tGetHandleVerifier [0x00007FF612D7DC75+12853]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF6130283C4+2250276]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612F676A6+1460486]\n",
      "\t(No symbol) [0x00007FF612B797CC]\n",
      "\t(No symbol) [0x00007FF612B7990C]\n",
      "\t(No symbol) [0x00007FF612BB3857]\n",
      "\t(No symbol) [0x00007FF612B9853F]\n",
      "\t(No symbol) [0x00007FF612B70617]\n",
      "\t(No symbol) [0x00007FF612BB1431]\n",
      "\t(No symbol) [0x00007FF612B98163]\n",
      "\t(No symbol) [0x00007FF612B6FB54]\n",
      "\t(No symbol) [0x00007FF612B6F000]\n",
      "\t(No symbol) [0x00007FF612B6F741]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFCDB4+1024020]\n",
      "\tMicrosoft::Applications::Events::EventProperty::~EventProperty [0x00007FF612C99A04+57108]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFBDB3+1019923]\n",
      "\tMicrosoft::Applications::Events::EventProperty::empty [0x00007FF612EFBA19+1019001]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1E031+394913]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1A954+380868]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D1AA99+381193]\n",
      "\tMicrosoft::Applications::Events::ILogConfiguration::operator* [0x00007FF612D12296+346374]\n",
      "\tBaseThreadInitThunk [0x00007FFD5F417374+20]\n",
      "\tRtlUserThreadStart [0x00007FFD6123CC91+33]\n",
      "\n",
      "Max captcha attempts reached\n"
     ]
    }
   ],
   "source": [
    "def t3(): \n",
    "    driver = open_driver(url)\n",
    "    login(driver)\n",
    "    driver = empty_carts(driver)  # Empty the cart\n",
    "    top10_names = fetch_top10_names(driver)  # Get the names of the 10 most expensive products\n",
    "    place_products_orders(driver, top10_names)  # Add these products to the cart\n",
    "    pay_for_order(driver)  # Proceed with the payment\n",
    "    driver.close()  # Close the browser\n",
    "\n",
    "# Execute Task 3\n",
    "t3()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAEjCAYAAAA8IcqvAAAgAElEQVR4Ae2d+3Nb13Xv8yf0L+gvdzrT25v2Nml6m+ZVp0lb107jmzjKRAqvKk5HTGPaKRVNaI5p8VKPSrIkioJYkrBImhBkgpRIQAxRxLBhsLAJ1DRFUCiPURmCBZGUqArQlfkYcsRBOPO9s88DOHjwIfCB15czMA7O2XvttT578bvX2aB1vgD+kAAJkAAJlDSBL5R0dAyOBEiABEgAFHomAQmQAAmUOAEKfYlPMMMjARIgAQo9c4AESIAESpwAhb7EJ5jhkQAJkACFnjlAAiRAAiVOgEJf4hPM8EiABEiAQs8cIAESIIESJ0ChL/EJZngkQAIkQKFnDpAACZBAiROg0Jf4BDM8EiABEqDQMwdIgARIoMQJUOhLfIIZHgmQAAlQ6JkDJEACJFDiBCj0JT7BDI8ESIAEKPTMARIgARIocQIU+hKfYIZHAiRAAhR65gAJkAAJlDiB3IR+dRYjHY04sL8Ce/ZW4kBtG5x3lnWowuit6UdId0YcznkuoLovrDub2U5uU3MI1YnXSZhvzuv6AKE+/fVDqK7feHxht9amHxvAYw/OXfBgLsU6sHTHBUNtFfbtrcCe/VWoOduPiVhaI34kARIggSIhkJPQh65U4WBXAHOrSpTxhwH0uvQiGkTnXhOkNAhRZyP2dAV1ZzPbiTb1zqSqxmccqN9fi6HZZDepqwKdk8nPc34TDu5vw+gT7Vx2u3v2VqNzUrcgxVyoP+JCVOsGIB4UthphDauLy2oc9/0WWP1xXSsekgAJkEDxEMhB6GNwHqlA+831gswUWtE6F6EHlPH0wp4u9IAYrxHJ9SFzfDF2rdGE+spGOB+qvmcI/TJG3qjAUU/qHcR6kfIaCZAACRQ6gRyEHoi6GrGvsh7tTh+kqRjiamWfDFYI7UlY/QFM6F7ujkNPXdFjduOKfunm5ip6caewNGlCdaMLUeFzhtALv+sxpC0Eq3EsLS4rr8TdQjJKHpEACZBAMRDISehFYPGHYbgHTTAcr8a+/VU46UputygVdu5Cv0fsjauvfT/P3KMXFb12Pft3BNkremVLKA7JVI2DXUEsbST0Yg9ffFfw88q0BaoYppY+kgAJkIBCIGehTwF4px/VKXvymUIr2ue2dZMykvwhc+smvU3m+Cl7/6sxOBur0e7oT9ujV7aJzvl0+/jC9KSJQp+OmJ9JgASKhkAOQh+H5HIhpPtTlSV/Bw5UWXR/ZZMptIJIwQi9cGbOh5Pir4bSvoxdGm3Dvuo2jDzUffnqb6PQF01K01ESIIF0AjkI/TIizjbUVFViT2U1DlZWYN8vLqT9eWURCD0g79cfTBN6AWjupgX1Ij5tC6myGkeduj/7SafIzyRAAiRQwARyEPoCjoaukQAJkAAJZBCg0Gcg4QkSIAESKC0CFPrSmk9GQwIkQAIZBCj0GUh4ggRIgARKiwCFvrTmk9GQAAmQQAYBCn0GEp4gARIggdIiQKEvrflkNCRAAiSQQYBCn4GEJ0iABEigtAhQ6EtrPhkNCZAACWQQoNBnIOEJEiABEigtAhT60ppPRkMCJEACGQQo9BlIeIIESIAESosAhb605pPRkAAJkEAGgRyEPgZnl0N5QpP8Tw+7Mp4NmzHKjp9YxmiL9ozaGJxvNKLdZEKnyYf76tjyA79bks+HjTrPot4o2pgwMqM0irpNMJhMMHT5Up4ju+PucwASIAES2EECuQn9NRN6rwWxlCb00bB4dOCU+tDweUTuTCHiDyASm8f9YADSrPpAj9Vl+fNEWHkqVfzhFKIpj+rbXF/tEYZzvn6Yu7QFRyxESUHX2IlHAk44k+ejTpPuGbMAVoOw2tV/ivhmP6yq+Gv9+U4CJEACxUogN6F3BoHwIMw3lxF1qgK7uoy5RQDLPlhd4uHaQXSe92FpNYahln5EVoGJK8rDSe47+jEqNH/GgaFJ8VjCdKFfp6/dghExjniWq6A+50OvO5b0QzxM/MIFDPl8GOqwYFT3gBQpRegv4JzDhxF7B8xj8/LzYzu1p4tPmqB/GHmxTi79JgESIAFBIHehF9W8y4JOo0PZuhGC2+fDhH8QZlkwg+jsCooncCcqbKlL2V6RrnXAqT40XNI/ySkxJ+v0tQ0mtmOAZYy0NMrbLe2NjThpV+4yEmZmlYVE+6wXeu0cMIshexBYDWDIoT73lhV9Eg+PSIAEip7AloQemMfIG+reeMwD8zUfRt0daN9A6OPBQXQ6fJj40CHvj895+uF+rGe5ttCLvu12H0acPkR0T/tL3FkghpEeC5yiou8ahCTvFsURDQZg7eiAW2wtiUXKZ4HZ5cOIwwTrpGgUhzRowpDPA3OXh3v0+ungMQmQQFETyEHoizpeOk8CJEACZUeAQl92U86ASYAEyo0Ahb7cZpzxkgAJlB0BCn3ZTTkDJgESKDcCFPpym3HGSwIkUHYEKPRlN+UMmARIoNwIUOjLbcYZLwmQQNkRoNCX3ZQzYBIggXIjQKEvtxlnvCRAAmVHgEJfdlPOgEmABMqNAIW+3Gac8ZIACZQdAQp92U05AyYBEig3AhT6cptxxksCJFB2BCj0ZTflDJgESKDcCOQg9DE4W87Kj+DrNDkgiYeAPMVPxOFARH4yVdoTnp7CRnrT6bdPw/ZAORu9/hqqTxlhbDPCfVdtGfXC+JIR44mO4zBUvCa3MfaNY0GcXxpH9ykDjKdOw/LJitLyt9Nwv22B+wMvvO9ZkGibsLNNBw9ssPm3yRbNkAAJkEAagdyEXjxhSvcjnhAVuRPERHAWc7Gw7nGCwNJMEBP+IO6rTxGcm1L/PfjEo/zmEZkST6RK/qw8uI3bt8bh9U9jISrB67utiDGAhbvj8PokRFUtxicWdF+06ITekDjWLK4sLGD6ui1V6JuTsi/aRa9b4JVtTsN22YsVrGD8ugPTWMG034vxW7cRfSzB/YG8LGDhQRRy88dRxZeVKG7fuo1x3zimH0ch+by4nfJv7ItBRCzjmFZMAL9V2kl+iyr0C4g+UAJL2FeDWI9Jhl0tcL6TAAmQQM5PmDpbj5NvnMXJN7TqvA29dwDcNMHgWwYeOmD+UCj7MubEUz5Wp2AVT3ECoD1lKvnM1kyhj14/iu5bAD424Kh7AZixwfjeAnDXorxjAQvycwQlWC5LWPHbEuIu+h7td8PdZ4DRpymqEPI0oa8ywu1zwHjcgtsAxpsN6kIQha3ZhijG4X5vAQtuG7xLwMoHymIy7lcWiPHrog0AbewHNhztki3BcNyNBUzD1ibe1Z8VL7r7pgGswPu2A2KZ8HZ14/ZvgZWPT8MoV/TjsF2XrSJhX+2+JhNh97IYdwXjl5RYtCH5TgIkQAKCwLZU9AnR1p61GnNBfv7qahhOkwujfg/abWsJfeZERK+rVbnfAIMQwAc2GIQA+i2waNsxAG53VeNwsxHGumpUn3JDyGjyZxqWvmTVnir0yVbwKQI+3W9RhV6r6Mfh/WAF0nWbbHf6bXF9Gm63Msp4v3JeL/SyjxiHQb5b0BYMdawHNhi7vPD6xEvcoURhe1vcOYhn52pbN+Ow9av2tYVE7b4mkwc2WD5Q7gKm+/WLmS5GHpIACZQ1gdyEvmcQE/IzX4OIPgHWFPonQVivuDDhG8TJnlShjwf70ekQ2zhh9PaFUyZhTVFbkdDdbIHbbYNbVPzaj1ZVi90RtxFGuxvufgO6/eo2SNgLx5nT6Na2fFYk2JotcIiKvllsz4jFxA3DJYfczxIQ/RbgtY9j4fE4bH0OSLfEuxu35TsJYOE9I7rdXtiOH1XuJrTFKIvQS13dkBCFu9kIh88Nm12SBT76ngHG33jhuFStVvQLcF/qhvsDG47+X+WOQekr7kjWWPwSdh0wXh5XFg6NC99JgARIILeKvoy4PfbC0ueGNLOAaNgLS7/6xW0ZIWCoJEACxU8gh4q++IN+6giWFrCg3Bw8dVd2IAESIIF8E6DQ53sGOD4JkAAJ7DABCv0OA6Z5EiABEsg3AQp9vmeA45MACZDADhOg0O8wYJonARIggXwToNDnewY4PgmQAAnsMAEK/Q4DpnkSIAESyDcBCn2+Z4DjkwAJkMAOE6DQ7zBgmicBEiCBfBOg0Od7Bjg+CZAACewwAQr9DgOmeRIgARLINwEKfb5ngOOTAAmQwA4TyFno42MdOPdh6gNDFF+DcDpjqW7HXHBOpp7ayqelOy4YWlzKvwe/hqF128QCMDdaIK3RVz69mTbr9ec1EiABEigQAjkK/TxGnDcwYRtEaFWNZHUZ94MBSDM+DGlCvxpDyB9AaNKhCP2TGKKzs5BuzkL8a7/K06fCiKo20j9HwwH5qVVL4vqTGCIP4/JgS4vLmHBuIPTrtIkvLuO+07Wu0G+mTYHMId0gARIggXUJ5Cb0nw7C+imAWQd6xxTxvW+3YEQ8P/ahQ3noCOIY7etHZBVYutkBs6joYy4Yrk0hLoRb9B1dBlZnMSQ/fSqIIfsssLqMOWEn5sKQeOjI6jzmxMOqdEIvIpI2EPqN2kQ3EHrRfzNt1qXLiyRAAiRQAARyEPo4RjtqUS8/SrAR1ec9EE8LlGyDuC8CWg2oFX0MTtsNyMvAQweGVKGXnzwl2k32o90VUB5gEozJ7ebueODsscAZFr2Wcd/vwlBPP0bTdoJEdwp9AWQPXSABEigKAk8v9HMe9HqSe/PxMRPMnwLx4CA6HT6MOttwTt26iXpMMHsCcPc0Jir6hNCLp091OTDi92HINwvEpzDi9GHC1w+rqPQfBuD8MIAJpwVO8Tzax9q4cUSDAVg7OuD2Kw8an/P0w53yIO7MNvrZmJsKwN3RAatfeUJWZn8gvY2+P49JgARIoJgIPL3QF2B08XBQ3iLK1bWt9s91XPYjARIggd0gsLHQj3iAzjbg/Cm+yIA5wBxgDuQjB4QGez/IeU1YW+gf/z/gpz8Afvd3+CID5gBzgDlQCDlQ8UNg7vOnFvy1hX7/jzixhTCx9IF5yBxgDuhz4B/3b5PQ3xwnWD1YHjMfmAPMgULKgeC6/7tnxkKQvaI3XeKkFtKk0hfmI3OAOaDPgR5ThpivdyK70IsvG/RGxfGe5/klTD6+hOGYzDvmQHnngNDedD0WOfEUP5sX+qc0/BQ+sCkJkAAJkMBaBIT2UujXosPzJEACJFACBCj0JTCJDIEESIAE1iNAoV+PDq+RAAmQQAkQoNCXwCQyBBIgARJYj0C+hN7/+FPwRQbMAeYAc2BnciBF9/Mp9OHFe+CLDJgDzAHmwPbmgFg8U34o9NsLmAlLnswB5kC+c4BCz7sI3kUxB5gDJZ4DFPoSn+B8VxIcn9UscyD/OUChp9CzmmMOMAdKPAco9CU+waym8l9NcQ44B/nOAQo9hZ7VHHOAOVDiOUChL/EJznclwfFZzTIH8p8DRSj0ElrPvYqG9iacaG/CGY+0RjUyjLqWYfna2Ptm9E5tH+yxATPsW1ggxt69iLo3m9Bw6hg6PhN+RWA3H0ND+zEc7hlBcPEegjfMqGtvQsP5IzjzUUQXYwS955qyjz8fgtN2DIdtSSbewSYcbm/C4VYrxrL5HOpDw3kxThMu63w509OFup5h2RfvO02ybz9tULg3fxRCOGMsCb1vnZLn5JXzfaljfT6C1hbFxitvKTbXju8eMvmocxe143C7MqdJ8chkF/adwgv/LMZrguzrYhabs8NoFnwFm4ZKnAlsX34kfaNNsiiMHChOoR9I/rIPm5tweVaBGQgOY8AzgrHPxeek0AdDo/A+CmFYUgXwkR/DnynimdonBO8tP5zvjshClXrtHsKREdm+vTeL0MvXhjGs+RLywzvhxMBHflkssyZ8yIxW3z2EPzOj+X3FH+9VI3of6ZJj3onWgaRwB94x4kRLlvFlEY8gMKtrPz+M5p5RZZHwGNEs6eyqom83d2FYHM87ccY8inCkDw3qeGMDTeiIaH0ktOq4i8UpZSzdIuK9qvonOIf0i9Q9DAykLQIiPnVhCkijCOjshDU+8rkQLr91EXUpPqzBzncKdYKr3pZ2nGLzHsLRYZxRF5+s7bV+fM/Ok1yKgkvRC72o3uRf6ltmnBBiOT+K5h6xECSFfmzgFFo/uwchogOP7iFgN6Jj5h7CWfo0nLMiIBaK9GuPnDhhGpGr74ELF1Mrav21TkU47e3H0CtEf7gJJ25kE50I7G8ZYReirsUgKk/VV010vLaLatV/D+EZK84MSlj/jmI4uTB8ZkadtkjoxtBshxcltLaY1epb4yWh400jej1WdLScQnNQ8z1d6MV53VjaL7wQTrNStYf1Qj9hxs8aK/Gzq/7EL4bz6quo/NWraA0pY6QKvY7P4j2IBa7jsyw+6OJKsPM14cdvWjFgv4jDvepCJ/uXalO+k9LmQPOf74n5SeaJlgN8L1YmRS/0YwMXlYreZ8RhmxMDHicGPhZVtCZcOvGc6cMZ+zBaTU6lyl6nTzj9WkrVnVZRZ7lmbzmlLAY6IdIniXfgIjpUgROVa7NH+SXSV/QBjxFnfFpFHMLlcy8r2zANL+NnvcMILIYwLOL16CthnfjOO9GsCatW0T/yw55gdA8DvWZ4hbhpFb18HEHgvyIIvm9O3C3Ji0J6NZ0u9J/70fpmH7zzawvCsLkrdZFcHEWzOXmHpjFK4TNrxeEGZWtLbB9p2zFy2zXYaXZEfNqWVYpNsT32/sWsdzlaX76vPY9kU1xsilPo3zRiwNOH5vZTOPGOWiE+GkZzq1muRJvfFVWchI72ixgIRXRVcgQDFypw4mN1kjL6JBeHcMY1CZdbL6LD04cTr6dV9Iu6a2o1u57QB945hld67MqiJIVkX2Xb75rRoO6LhwNGVLZadQtXMrHWrOhlETei7kIfBmS7Edh7mtD6bh9OrLFHH/yoCw1X7ejoVPfoH42gtd2MXrsRdb3K9wXKL3VaNZ0xVgiXzx9B87Cy2A6LO6aIFWccEsIRO0682YdeEV+nXd6eEfvwJ2x29F5twolhweCecocjV+/pfLTYdT5otjX2Onby/n9Pn1zRNwwq+ZHBfNaKV36lfOeg38ungGms+V5KuVCEQs8ELKUEZCzMZ+bAzucAhZ57styTZQ4wB0o8Byj0JT7BrJZ2vloiYzIu9Byg0FPoWc0xB5gDJZ4DFPoSn+BCrzToH6th5sDO5wCFnkLPao45wBwo8Ryg0Jf4BLNa2vlqiYzJuNBzgEJPoWc1xxxgDpR4DlDoS3yCC73SoH+shpkDO58DBSX0whm+yIA5wBxgDmx/DkD/c/4U8Lu/k/oS557i5wtZ226D4ax2eZIESIAESODpCGyDHlPonw45W5MACZDA7hKg0O8ub45GAiRAArtOgEK/68g5IAmQAAnsLgEK/e7y5mgkQAIksOsEKPS7jpwDkgAJkMDuEqDQ7y5vjkYCJEACu06AQr/ryDkgCZAACewuAQr97vLmaCRAAiSw6wR2Vej3PA+IAfkiA+YAc4A5sHs5ILR3R/7P2CtdmYbTB+JnMmIOMAeYA/nJgZ7up7qxyP5/xk7ezI/zTBpyZw4wB5gDG+fAf0rbIPTCxIEfbzwYJ4SMmAPMAebA7ubAzw88lciLxtkrenHl88dAxQ93NwAmDHkzB5gDzIG1c0Bo8tznWxP6u3fvIv31cOAqPj9zAnMNr/JFBswB5gBzIA858PjcP0Nocbo+b1bx167oN2uB7UiABEiABAqaAIW+oKeHzpEACZDA1glQ6LfOkBZIgARIoKAJUOgLenroHAmQAAlsnQCFfusMaYEESIAECpoAhb6gp4fOkQAJkMDWCVDot86QFkiABEigoAlQ6At6eugcCZAACWydAIV+6wxpgQRIgAQKmgCFvqCnh86RAAmQwNYJUOi3zpAWSIAESKCgCVDoC3p66BwJkAAJbJ1ATkI/57mA6ppDutdJmG/OZ3rzJIDOmnpYw6mX5nxtqDnuwP1V3fnlG2ivaYP7YVw9GUZvTRtG5nRt1EPRv7pPb1S01fsjjvsR0nUN9R2CwZfm46f9OjvZbKg2L3iQxQ3F+mMPztUPIqSPRR03ZKvHOY9+zGxjaH5mu5Y5voij91NdYOJQ+JAWrzi9dMeD9sYq7NtbgT37q1Df4UFkObVvxlweb4PVH0ttxE8kQAJFTSAnoY86G1HvTIpBfMaB+v21GJpNZTHnOYmaxkYcbLsBTb6VFsuYMFbhoCmonF+NwdlYmWITCKJzbwUOdKltNNNPguisqsCerqB2BkpbE9b7p/ilLiF2jXA+1HWbNKXZUa/FXKjfu769hBW5bUWa7wCynhcxbcLuOuOLODonE6MrB9nai3P7q2HwxRAXi1B8HlJPPfY1uhDVLUopc7kaR3TKA0N1+lykjcePJEACRUVgW4QeiMF5JE2AVsMwV5+Ee24WQ7WZiwCWg+isrkbn5DKE2MgClIJOiGItatL6ysJ0pDFNoDcWUCGQ57pMOFhtgqRVtdsl9DW1qKlsw+gTLYA4pK5a1B85lLYAbOynbCGbcKumNyv0oZ4qHLiiv+sBIOakqjJloUgRes39mUHU7NfHo13gOwmQQDES2B6hn82s6ONjbdinVvKiss8QHUErbMHB/ZXYJ0RFE98ERUUURydNONhyA0vi/PINGH5hQehmeiUu2p6E1R/AhPYKxlLuIjSBFMJW3RVU7G2X0B9xQXI2osam3tLMDKL2DR9CaXc+yp3H+n7K4W8g9EdtujhFvO4OVKfcKSgLb/vNBMzEwYQx9e4jq9DLd1OHYJ1JdOMBCZBAERPIWej3iH1f9bXv5+l79PNwn6yCWdtLfnIDhpSKN0lMCE+tI7kNlLyiVb/zGHnjEMxhINRzCCc/nAcyBHrzQi/ffWjbRBl21NHXEdqkf7q2R8R2SBjmX5zFyFzS30wR3dhP2eo644sFaytCL/rrt90yfRQeCD+rZOYZ8fIECZBA0RHIWej1YpERtajU91bioO4L0gP7K1BjT9vEB5AuPElbmtADEFsJh+tRWzeofIGbIdC6tkkDKUdaRS+flLeNGjHk6EjbAlK7rCO0KUbFB9FWCL348nO0DQfr6lGt3oFkiujGfsr21xk/JQ7NmSztJVMlqq9NaS3U91lYazaxdTPrQM1ebt2kweNHEihaAjsg9HGMtlXiaMpfmwAQ4lFlyfjrlE0JPeKQek7CHFS/0t2q0Ivpkhej9C911XnMIpxrzrBO6MXdgvvsWbjVG5R8Cr28OO5vhPWOuie2uoyIrRH7qlPnIN3H+FwY1sZKHOxJ299fEwAvkAAJFDqB7Rf6OQ+OZv0iT2znVMKQthm/OaFPw5hV6JNbScqWUupft2SrhIXI7Uv56x11nJyFPtXPdBHV/pJI2/LK5qdsYZ3xs8Wh/IVParzCzlKwH/VVleoWWyUONPZDWsz0Ue+P2IZr90wp32GkNuUnEiCBIiWQk9AXaax0mwRIgATKkgCFviynnUGTAAmUEwEKfTnNNmMlARIoSwIU+rKcdgZNAiRQTgQo9OU024yVBEigLAlQ6Mty2hk0CZBAORGg0JfTbDNWEiCBsiRAoS/LaWfQJEAC5USAQl9Os81YSYAEypIAhb4sp51BkwAJlBMBCn05zTZjJQESKEsCFPqynHYGTQIkUE4EKPTlNNuMlQRIoCwJUOjLctoZNAmQQDkRyEHoY3B2KQ/aUEClf9bjm0dkal5t5kKn7oHi+laZx0E412o7aUG90YROkwmGLk/Kg64z7ahnNtEn6jRhrSHXtMsLJEACJFAEBHIU+kZY1X9XfmnUgZNXVOFfXcb9YAATYeXJG3NTgzh6chATQuxjLnReC0DyBxB5rJJZjSHkD0CaST4cQ/SXZnwYklVXt1BoMCddSUG+6VCOF2dlu9KssLOM+9ri8iSG+7E4sGEfgEKvAeY7CZBAqRHITeidAYRcLtxfnYXTFcaEUxH6+45+5SHfMw4MTQpUQXRqD/aIuWDomwJWZzF0xYclxDHa14/IKrB004KhO8B9uwUj4sEYDx1q9Z9N6AfR7hYPx/bA3OZS+s8pdw0RmwMSANmPJ8Ccpx/uOQCTG/eh0JdaajMeEiABjUCOQh8Elm+g97gi7JIq9NK1Djj9QoQDkB6Kx/6lCr2ydaNt9cTgtN2A/HDAh8rCINkGcV94thpQK3rNTd27vjpXT4fEtstYAO6OQVnoMedBryeIoWuq/U30odDrGPOQBEigpAjkLvQA4k+UZ7hqQh8PDqLT4cPEhw6MzAhOMTiNJrhvzmJJbN3I2zGa0ANRjwlmTwDOnkFIy4DWf9TZhnNy2zB6+9KeXZoh2nFINgucfh+sb1gUoRd3C8ZDMH+qztUm+sSD/eh0TEHcAPCHBEiABEqJQA5CXwzhxzF6zaHcHRSDu/SRBEiABHaQQIkKvbjb2EFqNE0CJEACRUSgZIW+iOaArpIACZDAjhKg0O8oXhonARIggfwToNDnfw7oAQmQAAnsKAEK/Y7ipXESIAESyD8BCn3+54AekAAJkMCOEqDQ7yheGicBEiCB/BOg0Od/DugBCZAACewoAQr9juKlcRIgARLIPwEKff7ngB6QAAmQwI4SyEno/Y8/BV9kwBxgDjAHdiYHtlv1cxb68OI98EUGzAHmAHNge3NALJ7b/UOh54LFBZs5wBwooByg0BfQZLCK2d4qhjzJkzmg5ACFnkLPyos5wBwo8Ryg0Jf4BLOiYVXLHGAOUOgp9KzmmAPMgRLPAQp9iU8wqzlWc8wB5gCFnkLPao45wBwo8RwoQqGX0HruVTS0N+FEyzGc8UWyJOkIWq+OpJwfGzDDvoXJHHv3IurebELDqWPo+ExUCBHYzcfQ0H4Mh3tGEFy8h+ANM+ram9Bw/gjOfKT3K4Lec03Zx48O48x50ecYmm+IPordMz1dqOsZlu2mV2SZvkjofesUTrQ34ZXzfRhbvAfvO02ybz9tUFg1fxRCeD4Ep+0YDtsklY2E1n9+GYeFz+1WeNP5RJw48frFpN+SGQpfHp4AABSkSURBVIdbzWgVcb+j2VCrpYw47iHo65J5nGi5iN6IvqrK9DfwUZc8pw2tr+KF9mHFv88lDHS+jBM+te/sMJplX5twuKESZwJ6mzxOzxN+Zk5oOVCcQj+gCsGiH61XleOxG04MeEYwNi8mN4RhKaSIRWREPm/vzSL08rVhDM8qCREI+eGdcGLgI39WgZWhhcxoFcLzmRnN7yti7r1qRO8jXVLNO9E6kBTCwDtGnGjJMv7iPYwNdKl9/Wg12RGM9KFB7Ts20ISOFIHUjSFEWfNFJ9DelAVNQmuClegbQWBW75uE1hazvDBoCRF+5MdwSIkrOBuC3t6YzYwBma8frWanzCggjSKQLY7FUTSbtXlK81vv79VULsH3L6JZUts/CiFwS+Wt6xMWi8pb2RfBRBz69jxOKXrIaO18LFU2xSn0bxox4HGi92oTTgwrlWpAiHXUjma5Wh1GXcswwo+cOGESlX0EAxd0lan4xddf6+zC8OI92NuPoVfYGW7CiRvZkiEC+1tG2IWo+06hTq00xwZOoVWu8pU+XttFteq/h/CMFWcGJax1R2FvOaVWzJroSuh404hejxUdLafQHMzmhzin80XEM2VHw7GX8dNWpyy8SsKmC73oN6xbhCS0njmC1nftaG5pQu+M4JIUemEjxe8ZOxoaX8XPGn6JMx8ri4Em9JlxDKO58SJa3xe2jbBHs8QhBNusE+z5EZx5U1lAEr9wn6ULfVrcFHGKOHNgwxwoTqFPqVJVMX3LjgGPESfkalgV+pSqO7VyTK3IlWsJsdKJeEJwxHbIwEV0hFTBCpnR7FGO9RV9wGPUbSeFcPmcsjVyuOFl/Kx3GAFxt+ERdx9KJey92pWskkVFL5J2PoLAf0UQfN+My2LheeSHXfT5OHmnkeKLLtGD73fpFp2NhF4nvre60Kxtkejs6YXe3qMsiGKR6e1Rtog0PplxDKOhxakkYDbbn/vR+mYfvPIdguJHwNGE1ls6n4QfaUKfUvHr/NT84HsaPzLaUATLIWdKQ+g/68MJkx29g6dQpxf6RQmXWy+iw9OXutcsJ7/umlpVrif0gXeO4ZUesZg4MSBvC6n93zWjQdtLDxhR2WpV2uhEWSSSXjBTEuszKxo6++S7k2axr/9oBK3tZvTajajrVfb+U9ov3kOGL6JPS5cS53kzhhPimSb08oJhRN2FvkQMvZ0X0fGuHa2tatUdseKMQ9l2CkhOdFw4hTOeYXgfiT13Ixqu2jFgv4jDV0flXyD5DkcW5LQ4xMI42IQTdmG7S7kLStgO4fL5I2geFgueE8PiTkJU85266l7YnBnFgJhTkxN2sZ00a8Urv1K+cxDf0cjfO1DIKGTMgQ1zoAiFnhVLuvDzM3OCOcAcWC8HKPSsBjasBtZLIF6jwDAHCj8HKPQUego9c4A5UOI5QKEv8QlmtVX41RbniHO00zlAoafQs5pjDjAHSjwHKPQlPsE7XSnQPqtR5kDh5wCFnkLPao45wBwo8Ryg0Jf4BLPaKvxqi3PEOdrpHKDQU+hZzTEHmAMlngMU+hKf4J2uFGif1ShzoPBzoKCEXjjDFxkwB5gDzIHtzwFs888XttkezZEACZAACRQYAQp9gU0I3SEBEiCB7SZAod9uorRHAiRAAgVGgEJfYBNCd0iABEhguwlQ6LebKO2RAAmQQIERoNAX2ITQHRIgARLYbgIU+u0mSnskQAIkUGAEKPQFNiF0hwRIgAS2mwCFfruJ0h4JkAAJFBgBCn2BTQjdIQESIIHtJkCh326itEcCJEACBUaAQl9gE0J3SIAESGC7CVDot5so7ZEACZBAgRGg0BfYhNAdEiABEthuAilCf/fuXfBFBswB5gBzoDhyYLMLQorQb7YT25EACZAACRQPAQp98cwVPSUBEiCBnAhQ6HPCxk4kQAIkUDwEKPTFM1f0lARIgARyIkChzwkbO5EACZBA8RCg0BfPXNFTEiABEsiJAIU+J2zsRAIkQALFQ4BCXzxzRU9JgARIICcCFPqcsLETCZAACRQPAQp98cwVPSUBEiCBnAhQ6HPCxk4kQAIkUDwEKPTFM1f0lARIgARyIpCz0C/d8aC9sQr79lZgz/4q1Hd4EFlO8+GxB+dqDqFa9zp6JYC5VV27jDYnYRgMIKpvI5pntDuE6gsezGmmslzPGEtrq3sP9R1C76fqiSw2Er73hRO9RJ/EeTW2hA0A4rrBN59onziY88FQ049Q4gSAxSCsZ2sVjnsrcfC4BRMxfQMekwAJkMDWCOQm9DEX6vdXw+CLIS4EOT4Pqace+xpdqQIt2h1xIar5GJ/FUGMlauyz2hkgrU08NgV3W/XGtpIWlKM0O8g2VnofAFJXBTons1yYNGGP3nddkzX7qG3E9T1VJkhPdJ0Qh9RVhT17TZASp+fhPlmJeseswhHAXNgF61iWRSLRhwckQAIk8HQEchL6UE8VDlxJVrjykKthmKsqU0UzXXwBRJ2N2NMVTHqZpQ1WZ2GtrYRhLL5+u+TVjAVDXMoYS99ePV5TtLco9DW1tVkWtEbUpwh9EJ176zH0MItjPEUCJEAC20QgB6GPwXmkAu03Mz2YMFag3qnbdxAiXjeIyOIylsQrFoa1sRInP9RVrNmEXq20q21plX9NB9z+ACa011SanY3GynQ554r+qE3nhz+IqK56lxeP0SA6q9swKm9nLWO05RDM4QA6U4Q+DslUjX2/OIteTwCh2eVEZZ/FVZ4iARIggZwIbKvQC4HLEPr9Vep+djX27VW2e1I8XUfoD/To7hpEu42EfqOxUgZWPuRa0W8o9JPA3IdnUS1iCFtQ/YYPcxAVvH7rRvFhbioAZ18HTtZWYV9lLcyT6V92ZHGcp0iABEhgkwRyEHpAMlWi+tpU2hCzsNasv3UjtlL2yYKn65pV6GcxVFsBw2juWzdZx9INqx3mKvRZ9/VVowmb8hZULWrr6mGdERezC73mi3hf8l1Y87sBfTsekwAJkMBmCeQk9JgZRM3+RljvqJXn6jIitkbsq7YgpP9rmXQRF/v41VXonFxHwOPzCG3GVnqEmxkrvc8OfhmrLQTxoAVHe4JQIk4X+lmM2AOI6nDctzdizxs+LGXxladIgARIIBcCuQm9qDyD/aivqsQe8eeVeytxoLEf0mKaC+niK/qNtmFf7SDuawuCaCPbEHYqsKeyGkez/almejvRVv9XMZsZK8098TFRfadf2+DLWCVu1ee9qX+5s6bN9Ip+dR4TV07iYGUF9lVV48D+Cuyrt2Dicboz/EwCJEACuRPIWehzH5I9SYAESIAEdpMAhX43aXMsEiABEsgDAQp9HqBzSBIgARLYTQIU+t2kzbFIgARIIA8EKPR5gM4hSYAESGA3CVDod5M2xyIBEiCBPBCg0OcBOockARIggd0kQKHfTdociwRIgATyQIBCnwfoHJIESIAEdpMAhX43aXMsEiABEsgDAQp9HqBzSBIgARLYTQIU+t2kzbFIgARIIA8EKPR5gM4hSYAESGA3CVDod5M2xyIBEiCBPBCg0OcBOockARIggd0kQKHfTdociwRIgATyQIBCnwfoHJIESIAEdpPAjgq9430Pnq2oxP/41nfx9eefhe83x/Hxe8fhd5/EmOs4/O81wvfr13Go+if4h8of4TfvDO1m7ByLBEiABMqCwI4K/XMV/4Av/dVz+INv/iW++6O/w8P//Bc8kC4i8G9v4D995zE9cR6fjJzCC89/Hd/85pfx7e98tSygM0gSKBoCj8MIFfCjLUOfhosGZT4d3VGh/9r39uCPn/kb/ME3nsE3//av8TDYgsiNJtyfvIhpfxMi48245T2Jv/2rP8Uf/dHv4U+/8gdbYhG9fhSvtRlhvGTA6a5xrGzJ2jZ1nnHAaJ9WjH3SDcMHK8BjL2wfLGxxgNuw9d/OtLHixenX3Xg66+MwNI9n2ko7M95swMat0jqpH6PXbZvsu4Db4afzPvuIPKsnsHTHBUOLC1H9yQ2Olyb7YTCa0GkyYejTOLAYxJBJ+XzysAkSgHjYJV/vbLuA3qD6lPvVGCZ6GmGeTB9gGZKtDdbBQbQPBrEkLq/G4O4ywWo3odMdS++w9mfRr6MNnSYLOnt8clxLQYfiS9dZ1JiCct85Xz86e0zoPN8BzfyaLLL4sjQ5CINtEFbjIKTltd0p9Cs7KvTf+v6P8bVvfB+//6Wv4dnnf4AHkgEfu47hw6EjePdqLW4OH8ftj07h+b/5M3zxD/8bvvTl398SL72YTPcrwrLwYBrTt9yQHgD4bRSSz4vxu5lCsnB3HF7/NKZnovICsfIgiumZcbXtAqb9Xng/Sf6ayO19EqK/BbASRXRmGuM+L25nqX6idgNst8bRrS0+K1HcfqAsQ9FPvPD6bieFOSrB6xvHtOriyoPbuH1L8W1Bvqa1zS6IC+/Z4P3YAssnGsoF2bfbIu4ZZUwttuS4eqHPjFWzNN58Go5bXpmTYimzbfZ4JIz3JYVebuOfVmNOtbEQ7sbhX3XDq4p9alvNE74/LYGlxWVMODOFPv54ChE5Z+cRCcegSrVsXnI4si8MyzfQa59NdWE1AKdrXjn3ZBlLsy4404X+sQudTkXMo04TnGLcoAmdajvJpCweqYbX+BRzYehm9mtLo/0Ymkm79tAFp6L9WItFpi/zcJpUZjEXOrX40kwXw8cdFfq/+MFP8Bff24MvfvXr+Pbzz2L2P87hgXQeDz5pxv3/OIf7N8/iP4aP4oXnvor/+ce/hy//6X/fErPodSO6fV543TYYLnllIRm/eBRuOZFX4O3qxu3fAisfG2G5pRvqrgXG94SyTsPWbJOTO3r9NLpvKXI23d8Nryg/7lpg8Yt3G7pFZY5pWPrGgQc2nL4squtpWNqyVdNR2F56DW5tfXlgg+G6WDQWsCDOLblhsUeBFS+6ZTsrGL9kgbAo7lK6ha8fG3BUGJixqb7qxVmLRYLlbVFnTcPW5VXvaMZhOK74NN1vlH2QYxN3vEvjMPaJ9klbGbFqpkWrZjUGnwHGT4DMtuvEc8aoVPQPbLD4xKK7gIWlbDaSvgiu+rY6V3iYAwEpi9AD8xjpcWDCaYHzYarRpTs+mDs6YLb7cF9XzYauWTD6JNk24jiLo7VnU/vHsgg9YnBf6ceI3wd3RwesQoyfBGG94sKEzwPrBQtG9SvNjE+p0OW7CAekxeSYWJ3HxGAHOk2DcAbVBUZcXg2j98oN3YI1j1HTWdQ3mjCh65+VRRZfom4Len0BjLg70D6Ytrjp3Cn0wx0V+q+/sAdf+utn8cW/eAav1u3Hvw++ivev1eKjodfhfPuf8Om/NeDqm/+I7//t1/Bn/+uL+NKWt26SVaMGPrndEIXtbVX8ZmywCcHWfgIWWO4qH8b7NaE3wCbuAoTAXT4Nm1hAfF5IohL3d+P0deWzNxDFSkK4o4mFQump/HfaboRDX9Fr7R+70d3lhtfXDaMQfiFs8gIiBFCJJXpd9cNvgEH4rPXVibM21orPgIpfHMbhXx1G9U9eg0Ne4MZhbBNiDsBvlAVaLIjKtShsl8QikBTXjFg147LQq1s3qi8ZbTcRD7CCaZ8DlkvdcD/IwlbnS3pbnSs8zIFAVnET673fhJqugLKVks3u6hSsdrUcnvOh05FN8GZhtalthI2sQi+EOI6l5TiWRl0Y0YRXnHsC3He6ENKPv57Q69ot+QaVuwMAcx+aMJTNvSc3YFXvJkTXtVjI/qX5El9eRnz5Bpwf6lY73fjFcLijQv/n33sRX/7us/ijbz2Dcyf248OBQ3i9dh9+bT6EvpYq+AZr8a/mV/CTF7+Dbz/zJ/jqn//hlpjpt240Q0mhB6LvGWD8jReOS90YlzcItVbTcLSdRndbN44mKvqk0K8ELDD0u+F9zwK3WBBWJFiabXD73LC4p3Xim0XoZ2wwiGpd/Ny14PR1XfsHDhiF0P/GgNNyhR+Fu9kIh88B42XlO4bNC/0CHF2O5BbQiheGS2q1/ven4XC70d2s3SW8hsNi3OtGGH3iliIKx8VujD9YQUasGqIsQp/Rdr14XtIqei9s73nlsW23kGW8KBynDHB8PI2FB6ltda7w8KkIxBENBmDt6IDbP4U5fd+HLphdMUB7T1xbhmQ3odfpg1vsq08qIheyWSDpqvmozwKzy4cRhwnmMbWynpvChKiAbQFID0WJHkZvX1hs6GPI5MCIpx/t9rBSdcd8MPd55P6do0+xRz/rQWeXA26fC51dHkRXlWre2hPUVfNxhJwmWD0BuHva4JwSwWWymPP0K3f9Gb7EEXKYMOTzoNfoQEgXdwJTkRzsqNB/44Uf4yt/9Ry+8pffRVvTQYzb63Cl9Z/wr+bD6Gl5Cf8++BqG+2uxd8938L//7hk8860/yRO2adz+JIqFhduwdWXbesmTW9sybLJa18wlFg/tBN9JYC0C/KubtcgU1fkdFfpnXtyHP3vuBXzlu3+DSy0vITJ6Eh8OHYXv10fw0dARjDteh8/+Giorvoc9P/wunnkmX0IPrCxMQ/pkGiviy9US+1lJuXsRdyQrhfEXSSXGmeGQQKES2FGh3//LOjz7f6rwrR/8GJfaf4Wb/3Yc9rcPw37ll/hN76vw/PoIrl2pwzeeew7f/sEP8aN/OFionOgXCZAACRQtgR0Verd3DCetH+G1S/+Cl15/FW/023Dgl+fw4t//FM/95EXsrfsp/vrHe/CN77+IF19+Ce96PEULko6TAAmQQKES2FGhL9Sg6RcJkAAJlBMBCn05zTZjJQESKEsCFPqynHYGTQIkUE4EKPTlNNuMlQRIoCwJUOjLctoZNAmQQDkRoNCX02wzVhIggbIkQKEvy2ln0CRAAuVEgEJfTrPNWEmABMqSAIW+LKedQZMACZQTAQp9Oc02YyUBEihLAhT6spx2Bk0CJFBOBCj05TTbjJUESKAsCVDoy3LaGTQJkEA5EaDQl9NsM1YSIIGyJEChL8tpZ9AkQALlRIBCX06zzVhJgATKkgCFviynnUGTAAmUEwEKfTnNNmMlARIoSwIU+rKcdgZNAiRQTgQo9OU024yVBEigLAn8f/M9T6nVqj4+AAAAAElFTkSuQmCC"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 4: Flash sale (bonus)\n",
    "\n",
    "This task is time-limited, and only the first few orders will secure the products for you. We count the time based on the payment time rather than the order time. We will randomly reduce prices for select items in a period of time. We will anounce you the time slot in class. Your task is to identify these discounted products, place the order, and complete the payment. Successful purchases will be marked as delivered, as shown in the image.\n",
    "\n",
    "\n",
    "![image.png](attachment:image.png)\n",
    "\n",
    "1. You are expected to crawl and store the names and prices of all products in advance.\n",
    "2. There will be 4 rounds for the flash sale, with the quota decreasing as each round progresses.\n",
    "3. Only an order with completed payment and each order containing only one product will be considered a valid order.\n",
    "4. Submit your purchasing code in the following code block. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "def t4():\n",
    "    return 0"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "cisc7201",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
